import requests
import requests.adapters
import urllib.request, urllib.error, urllib.parse
import http.cookiejar

# from ...core.config.global_var import Variables
from ...core.exception.exception_go import *

from CoTec.core.exception.exception_go import ExceptionGo as E
from CoTec.utility.file.file_go import FileHelper as file
from CoTec.utility.string.string_go import StringHelper as string
from CoTec.core.request.proxy_go import ProxyHelper

from CoTec.utility.spider.spider import spider

class RequestHelperClassVer:
    session = requests.Session()
    adapters = requests.adapters.HTTPAdapter(pool_maxsize=5000, pool_connections=5000)

    session.mount('http://', adapters)
    session.mount('https://', adapters)

    proxy_helper = ProxyHelper()

    config = None

    error_result = ['{"success":true,"value":-999}']
    codes = ['gb2312', 'gbk', 'utf-8']

    @staticmethod
    def init(conf):
        RequestHelperClassVer.config = conf

    # def __init__(self):
    #     if RequestHelperClassVer.first is None:
    #         RequestHelperClassVer.first = True
    #         return
    #
    #     if RequestHelperClassVer.config is not None:
    #         self.config = RequestHelperClassVer.config
    #     else:
    #         raise Exception("RequestHelperClassVer.config has not being initiated!")

    def __to_encode(self, req, **pars):
        html_doc = req.text

        incode = spider.get_txt_page_encode(html_doc)

        if incode is not None and incode != '':
            encode = incode.lower()
            if encode in self.codes:
                try:
                    html_doc = str(req.content, encode)
                except UnicodeDecodeError as e:
                    if req.encoding == 'ISO-8859-1':
                        encodings = requests.utils.get_encodings_from_content(req.text)
                        if encodings:
                            encoding = encodings[0]
                        else:
                            encoding = req.apparent_encoding

                        encode_content = req.content.decode(encoding, 'replace').encode('utf-8', 'replace')
                        html_doc = str(encode_content, 'utf-8')

        #过滤html标签
        html_doc = string.html_tag_killer(html_doc)

        return html_doc

    def __in__get(self, url, **pars):
        header = \
            {
                "User-Agent":
                    # "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_11_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/55.0.2883.95 Safari/537.36"
                    "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_11_6) AppleWebKit/536.26 (KHTML, like Gecko) Mobile/10B329 MicroMessenger/6.5.7"
            }

        if RequestHelperClassVer.config.proxy_enable:
            req = self.session.get(url, headers=header, proxies=self.proxy_helper.get_proxy())
        else:
            req = self.session.get(url, headers=header)

        # req = self.session.get(url, headers=header)

        return self.__to_encode(req, **pars)

    def __in_get(self, url, ** pars):
        header = \
            {
                "User-Agent":
                    "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_11_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/55.0.2883.95 Safari/537.36"
            }

        session = self.session

        stream = False
        if 'stream' in pars:
            if pars['stream'] == True:
                stream = True

        if 'header' in pars:
            header = pars['header']

        cookies = None
        if 'cookies' in pars:
            cookies = pars['cookies']
        elif 'file_cookie' in pars:
            path = pars['file_cookie']
            if path is not None:
                cookies = self.__read_cookie_from_file(path)

        if RequestHelperClassVer.config.proxy_enable:
            req = session.get(url, headers=header, proxies=self.proxy_helper.get_proxy(), timeout=self.config.request_timeout, stream=stream, cookies=cookies)
        else:
            req = session.get(url, headers=header, timeout=self.config.request_timeout, stream=stream, cookies=cookies)

        return self.__to_encode(req, **pars)

    def __in_post(self, url, par, ** pars):
        session = self.session

        cookies = None
        if 'cookies' in pars:
            cookies = pars['cookies']
        elif 'file_cookie' in pars:
            path = pars['file_cookie']
            cookies = self.__read_cookie_from_file(path)

        json = None
        if 'json' in pars:
            json = pars['json']

        if self.config.proxy_enable:
            req = session.post(url, par, proxies=self.proxy_helper.get_proxy(), timeout=self.config.request_timeout, cookies=cookies, json=json)
        else:
            req = session.post(url, par, timeout=self.config.request_timeout, cookies=cookies, json=json)

        return self.__to_encode(req, **pars)

    def __in_post_ex(self, url, par, ** pars):
        header = None

        if "header" in pars:
            header = pars["header"]

        session = self.session

        cookies = None
        if 'cookies' in pars:
            cookies = pars['cookies']
        elif 'file_cookie' in pars:
            path = pars['file_cookie']
            cookies = self.__read_cookie_from_file(path)

        if self.config.proxy_enable:
            req = session.post(url, par, headers = header, proxies=self.proxy_helper.get_proxy(), timeout=self.config.request_timeout, cookies=cookies)
        else:
            req = session.post(url, par, headers=header, timeout=self.config.request_timeout, cookies=cookies)

        return self.__to_encode(req, **pars)



    def get(self, url, **pars):
        result = None
        for i in range(0, self.config.request_retry_times):
            try:
                result = self.__in_get(url, **pars)
                break
            except Exception as e:
                E.out_err(e)

        if result != None:
            return result
        else:
            raise HttpConnectionFailedException(url)

    def post(self, url, par=None, ** pars) -> str:
        result = None
        for i in range(0, self.config.request_retry_times):
            try:
                result = self.__in_post(url, par, ** pars)

                break
            except Exception as e:
                E.out_err(e)

        if result != None:
            return result
        else:
            raise HttpConnectionFailedException(url)

    def post_ex(self, url, par, ** pars):
        result = None
        for i in range(0, self.config.request_retry_times):
            try:
                result = self.__in_post_ex(url, par, ** pars)
                break
            except Exception as e:
                pass

        if result != None:
            return result
        else:
            raise HttpConnectionFailedException(url)





    def _get(self, url, **pars):
        result = None
        for i in range(0, self.config.request_retry_times):
            try:
                result = self.__in__get(url, **pars)
                break
            except Exception as e:
                pass

        if result != None:
            return result
        else:
            raise HttpConnectionFailedException(url)









    # def __request_wrapper(self, func, url, pars):
    #     result = None
    #     for i in range(0, self.config.request_retry_times):
    #         try:
    #             result = func(url, pars)
    #             break
    #         except Exception as e:
    #             pass
    #
    #     if result != None:
    #         return result
    #     else:
    #         raise HttpConnectionFailedException(url)

    def __read_cookie_from_file(self, path:str) -> dict:
        try:
            cookie = file.read(path)
            return string.str_to_dic_ex(cookie, ';', '=')
        except:
            return {}












    # def get(self, url, **pars):
    #     result = None
    #     for i in range(0, self.config.request_retry_times):
    #         try:
    #             result = self.__in_get(url, **pars)
    #             break
    #         except Exception as e:
    #             E.out_err(e)
    #
    #     if result != None:
    #         return result
    #     else:
    #         raise HttpConnectionFailedException(url)
    #
    # def post(self, url, par=None, **pars) -> str:
    #     result = None
    #     for i in range(0, self.config.request_retry_times):
    #         try:
    #             result = self.__in_post(url, par, **pars)
    #
    #             break
    #         except Exception as e:
    #             E.out_err(e)
    #
    #     if result != None:
    #         return result
    #     else:
    #         raise HttpConnectionFailedException(url)
    #
    # def post_ex(self, url, par, **pars):
    #     result = None
    #     for i in range(0, self.config.request_retry_times):
    #         try:
    #             result = self.__in_post_ex(url, par, **pars)
    #             break
    #         except Exception as e:
    #             pass
    #
    #     if result != None:
    #         return result
    #     else:
    #         raise HttpConnectionFailedException(url)
    #
    # def _get(self, url, **pars):
    #     result = None
    #     for i in range(0, self.config.request_retry_times):
    #         try:
    #             result = self.__in__get(url, **pars)
    #             break
    #         except Exception as e:
    #             pass
    #
    #     if result != None:
    #         return result
    #     else:
    #         raise HttpConnectionFailedException(url)









